package cn.mw.cmdb.template.service.impl;

import cn.mw.cmdb.entity.InstanceInfoExtend;
import cn.mw.cmdb.entity.sanxia.FileInfo;
import cn.mw.cmdb.exception.ZabbixResultException;
import cn.mw.cmdb.template.constant.MwTemplateConfigurationConstant;
import cn.mw.cmdb.template.entity.MonitorItemDto;
import cn.mw.cmdb.template.entity.convert.MwMonitorItemConvertDto;
import cn.mw.cmdb.template.param.*;
import cn.mw.cmdb.template.service.MwTemplateConfigurationService;
import cn.mw.cmdb.template.service.MwZabbixHandlerService;
import cn.mw.cmdb.util.FilePost;
import cn.mw.main.api.common.ZabbixDubboService;
import cn.mw.microMonitorCommon.api.opsengine.OpsengineApi;
import cn.mw.microMonitorCommon.constants.ZabbixApiConstants;
import cn.mw.microMonitorCommon.constants.ZabbixMethodConstants;
import cn.mw.microMonitorCommon.entity.autops.AutopsReferencingScript;
import cn.mw.microMonitorCommon.entity.zabbix.MWZabbixAPIResult;
import cn.mw.microMonitorCommon.util.ListMapObjUtils;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * @author gengjb
 * @description zabbix数据处理接口
 * @date 2024/10/21 9:28
 */
@Slf4j
@Service
public class MwZabbixHandlerServiceImpl implements MwZabbixHandlerService {

    @DubboReference(check = false, timeout = 120000)
    public ZabbixDubboService zabbixDubboService;
    @DubboReference(check = false, timeout = 120000)
    public OpsengineApi opsengineApi;

    @Value("${yunzhihui.destinationPath}")
    public String destinationPath;


    @Value("${yunzhihui.workflowId}")
    public String workflowId;

    @Value("${yunzhihui.url}")
    public String url;


    @Value("${yunzhihui.sendUrl}")
    public String sendUrl;
    @Value("${yunzhihui.open}")
    public Boolean open;

    @Value("${yunzhihui.workOrderId}")
    public String workOrderId;

    @Value("${yunzhihui.menuId}")
    public String menuId;

    @Value("${yunzhihui.accountId}")
    public String accountId;

    @Value("${yunzhihui.userid}")
    public String userid;

    @Value("${yunzhihui.type}")
    public String fileType;
    public final String HOST_IDS = "hostids";
    public final String MACRO = "{#IFNAME}";
    private final String FILTER = "filter";
    private final String CONDITIONS = "conditions";
    public final String INTERFACE_RULE_NAME = "Network Interfaces Discovery";

    private final String TRIGGER_ID = "triggerid";

    private MwTemplateConfigurationService templateConfigurationService;

    public MwZabbixHandlerServiceImpl(MwTemplateConfigurationService templateConfigurationService) {
        this.templateConfigurationService = templateConfigurationService;
    }

    @Override
    public void updateDiscoveryRuleFilterInfo(ZabbixHandlerParam param) {
        if(StringUtils.isEmpty(param.getHostId()) || param.getServerId() == null){
            return;
        }
        //获取主机的接口发现规则
        Map zabbixRuleParam = new HashMap();
        zabbixRuleParam.put(HOST_IDS,param.getHostId());
        zabbixRuleParam.put(MwTemplateConfigurationConstant.OUTPUT,MwTemplateConfigurationConstant.EXTEND);
        zabbixRuleParam.put(MwTemplateConfigurationConstant.selectFilter,MwTemplateConfigurationConstant.EXTEND);
        MWZabbixAPIResult zabbixAPIResult = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.GET_CUSTOM_INFO_BY_METHOD, param.getServerId(), ZabbixMethodConstants.DISCOVERY_RULE_GET, zabbixRuleParam);
        if(zabbixAPIResult == null || zabbixAPIResult.isFail()){
            log.error("updateDiscoveryRuleFilterInfo{} discoveryruleGET error>>>"+zabbixRuleParam);
            throw new ZabbixResultException(String.valueOf(zabbixAPIResult.getData()));
        }
        List<DiscoveryRuleParam> discoveryRuleParams = JSONArray.parseArray(String.valueOf(zabbixAPIResult.getData()), DiscoveryRuleParam.class);
        if(CollectionUtils.isEmpty(discoveryRuleParams)){
            return;
        }
        List<DiscoveryRuleParam> ruleParams = discoveryRuleParams.stream().filter(item -> item.getName().equals(INTERFACE_RULE_NAME)).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(ruleParams)){
            return;
        }
        DiscoveryRuleParam discoveryRuleParam = ruleParams.get(0);
        if(CollectionUtils.isEmpty(param.getInterfaceNames())){//接口信息为空，直接停用该发现规则
            //停用规则
            Map updateParam = new HashMap();
            updateParam.put(MwTemplateConfigurationConstant.ITEM_ID,discoveryRuleParam.getItemid());
            updateParam.put(MwTemplateConfigurationConstant.STATUS,1);
            MWZabbixAPIResult result = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.GET_CUSTOM_INFO_BY_METHOD, param.getServerId(), ZabbixMethodConstants.DISCOVERY_RULE_UPDATE, updateParam);
            if(result == null || result.isFail()){
                log.error("updateDiscoveryRuleFilterInfo{} discoveryruleENABLE error>>>"+updateParam);
                throw new ZabbixResultException(String.valueOf(result.getData()));
            }
            return;
        }
        List<String> interfaceNames = param.getInterfaceNames();
        Boolean status = param.getStatus();
        //接口信息不为空，增加过滤规则
        DiscoveryRuleFilterParam filter = new DiscoveryRuleFilterParam();
        filter.setEvaltype("0");
        List<DiscoveryRuleFilterParam.FilterCondition> conditions = new ArrayList<>();
        for (DiscoveryRuleFilterParam.FilterCondition condition : discoveryRuleParam.getFilter().getConditions()) {
            if(status != null && !status && !interfaceNames.contains(condition.getValue())){
                DiscoveryRuleFilterParam.FilterCondition filterCondition = filter.new FilterCondition();
                filterCondition.setMacro(condition.getMacro());
                filterCondition.setValue(condition.getValue());
                conditions.add(filterCondition);
            }else if(!condition.getMacro().equals(MACRO)){
                DiscoveryRuleFilterParam.FilterCondition filterCondition = filter.new FilterCondition();
                filterCondition.setMacro(condition.getMacro());
                filterCondition.setValue(condition.getValue());
                conditions.add(filterCondition);
            }
        }
        if(status != null && status) {
            for (String interfaceName : param.getInterfaceNames()) {
                DiscoveryRuleFilterParam.FilterCondition condition = filter.new FilterCondition();
                condition.setMacro(MACRO);
                condition.setValue(interfaceName);
                conditions.add(condition);
            }
        }
        filter.setConditions(conditions);
        Map updateParam = new HashMap();
        updateParam.put(MwTemplateConfigurationConstant.ITEM_ID,discoveryRuleParam.getItemid());
        updateParam.put(FILTER,filter);
        updateParam.put(MwTemplateConfigurationConstant.STATUS,0);
        hanlderFilter(updateParam);
        MWZabbixAPIResult result = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.GET_CUSTOM_INFO_BY_METHOD, param.getServerId(), ZabbixMethodConstants.DISCOVERY_RULE_UPDATE, updateParam);
        if(result == null || result.isFail()){
            log.error("updateDiscoveryRuleFilterInfo{} discoveryruleUPDATE error>>>"+updateParam);
            throw new ZabbixResultException(String.valueOf(zabbixAPIResult.getData()));
        }
    }

    @Override
    public void interfaceTriggerDeactivate(ZabbixHandlerParam param) {
        if((CollectionUtils.isEmpty(param.getInterfaceNames()) && CollectionUtils.isEmpty(param.getDisplayInterfaceList())) || StringUtils.isEmpty(param.getHostId()) || param.getServerId() == null){
            return;
        }
        //查询对应主机的对应接口触发器
        Map zabbixTriggerParam = new HashMap();
        zabbixTriggerParam.put(HOST_IDS,param.getHostId());
        zabbixTriggerParam.put(MwTemplateConfigurationConstant.OUTPUT,MwTemplateConfigurationConstant.EXTEND);
        MWZabbixAPIResult trighgerResult = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.GET_CUSTOM_INFO_BY_METHOD, param.getServerId(), ZabbixMethodConstants.TRIGGER_GET, zabbixTriggerParam);
        if(trighgerResult == null || trighgerResult.isFail()){
            log.error("updateDiscoveryRuleFilterInfo{} triggerGET error>>>"+zabbixTriggerParam);
            throw new ZabbixResultException(String.valueOf(trighgerResult.getData()));
        }
        List<TriggerParam> triggerParams = JSONArray.parseArray(String.valueOf(trighgerResult.getData()), TriggerParam.class);
        if(CollectionUtils.isEmpty(triggerParams)){
            return;
        }
        Boolean status = param.getStatus();
        List<String> interfaceNames = param.getInterfaceNames();
        List<Map> updateTriggerParam = new ArrayList<>();
        for (TriggerParam triggerParam : triggerParams) {
            String description = triggerParam.getDescription();
            String name = matchInterfaceName(description);
            Map triggerMap = new HashMap();
            if(CollectionUtils.isNotEmpty(param.getInterfaceNames()) && status != null && status && name != null && interfaceNames.contains(name)){
                triggerMap.put(TRIGGER_ID,triggerParam.getTriggerid());
                triggerMap.put(MwTemplateConfigurationConstant.STATUS,0);
                updateTriggerParam.add(triggerMap);
                continue;
            }
            if(CollectionUtils.isNotEmpty(param.getInterfaceNames()) && status != null && !status && name != null && interfaceNames.contains(name)){
                triggerMap.put(TRIGGER_ID,triggerParam.getTriggerid());
                triggerMap.put(MwTemplateConfigurationConstant.STATUS,1);
                updateTriggerParam.add(triggerMap);
            }
            if(CollectionUtils.isNotEmpty(param.getDisplayInterfaceList()) && param.getDisplayInterfaceList().contains(name)){
                Map triggerDisplayMap = new HashMap();
                triggerDisplayMap.put(TRIGGER_ID,triggerParam.getTriggerid());
                triggerDisplayMap.put(MwTemplateConfigurationConstant.STATUS,1);
                updateTriggerParam.add(triggerDisplayMap);
            }
        }
        if(CollectionUtils.isEmpty(updateTriggerParam)){
            return;
        }
        MWZabbixAPIResult zabbixAPIResult = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.GET_CUSTOM_INFO_BY_METHOD, param.getServerId(), ZabbixMethodConstants.TRIGGER_UPDATE, updateTriggerParam);
        if(zabbixAPIResult == null || zabbixAPIResult.isFail()){
            log.error("updateDiscoveryRuleFilterInfo{} triggerUPDATE error>>>"+updateTriggerParam);
            throw new ZabbixResultException(String.valueOf(zabbixAPIResult.getData()));
        }
    }

    @Override
    public void updateMonitorItemStatus(ZabbixHandlerParam param) {
        if((CollectionUtils.isEmpty(param.getInterfaceNames()) && CollectionUtils.isEmpty(param.getDisplayInterfaceList())) || StringUtils.isEmpty(param.getHostId()) || param.getServerId() == null){
            return;
        }
        List<String> itemNames = new ArrayList<>();
        if(CollectionUtils.isNotEmpty(param.getInterfaceNames())){
            itemNames.addAll(param.getInterfaceNames());
        }
        if(CollectionUtils.isNotEmpty(param.getDisplayInterfaceList())){
            itemNames.addAll(param.getDisplayInterfaceList());
        }
        //查询监控项
        MWZabbixAPIResult mwZabbixAPIResult = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.ITEM_GET_BY_SEARCH, param.getServerId(),itemNames,param.getHostId());
        if(mwZabbixAPIResult == null || mwZabbixAPIResult.isFail()){
            log.error("updateMonitorItemStatus{} itemGET error>>>"+param);
            throw new ZabbixResultException(String.valueOf(mwZabbixAPIResult.getData()));
        }
        List<MwMonitorItemConvertDto> items = JSONArray.parseArray(String.valueOf(mwZabbixAPIResult.getData()), MwMonitorItemConvertDto.class);
        if(CollectionUtils.isEmpty(items)){
            return;
        }
        //修改监控项状态
        List<Map> updateItemParam = new ArrayList<>();
        for (MwMonitorItemConvertDto item : items) {
            Map itemMap = new HashMap();
            String name = matchItemName(item.getName());
            if(CollectionUtils.isNotEmpty(param.getInterfaceNames()) && param.getStatus() != null && param.getStatus() && StringUtils.isNotEmpty(name) && param.getInterfaceNames().contains(name)){
                itemMap.put(MwTemplateConfigurationConstant.ITEM_ID,item.getItemid());
                itemMap.put(MwTemplateConfigurationConstant.STATUS,0);
                updateItemParam.add(itemMap);
                continue;
            }
            if(CollectionUtils.isNotEmpty(param.getInterfaceNames()) && param.getStatus() != null && !param.getStatus() && StringUtils.isNotEmpty(name) && param.getInterfaceNames().contains(name)){
                itemMap.put(MwTemplateConfigurationConstant.ITEM_ID,item.getItemid());
                itemMap.put(MwTemplateConfigurationConstant.STATUS,1);
                updateItemParam.add(itemMap);
                continue;
            }
            if(CollectionUtils.isNotEmpty(param.getDisplayInterfaceList())){
                Map disPlayItemMap = new HashMap();
                if(StringUtils.isEmpty(name) || !param.getDisplayInterfaceList().contains(name)){
                    continue;
                }
                disPlayItemMap.put(MwTemplateConfigurationConstant.ITEM_ID,item.getItemid());
                disPlayItemMap.put(MwTemplateConfigurationConstant.STATUS,1);
                updateItemParam.add(disPlayItemMap);
            }
        }
        MWZabbixAPIResult zabbixAPIResult = zabbixDubboService.getZabbixApiResult(ZabbixApiConstants.GET_CUSTOM_INFO_BY_METHOD, param.getServerId(), ZabbixMethodConstants.ITEM_UPDATE, updateItemParam);
        if(zabbixAPIResult == null || zabbixAPIResult.isFail()){
            log.error("updateMonitorItemStatus{} itemUPDATE error>>>"+param);
            throw new ZabbixResultException(String.valueOf(zabbixAPIResult.getData()));
        }
    }

    @Override
    public void instanceSendScript(ZabbixHandlerParam param) {
        if(StringUtils.isEmpty(param.getTemplateId())||open){
            return;
        }
        MwTemplateConfigurationParam templateConfigurationParam = new MwTemplateConfigurationParam();
        templateConfigurationParam.setPageNum(null);
        templateConfigurationParam.setPageSize(null);
        templateConfigurationParam.setServerId(param.getServerId());
        templateConfigurationParam.setTemplateId(param.getTemplateId());
        Object detailInfo = templateConfigurationService.getTemplateDetailInfo(templateConfigurationParam);
        if(detailInfo == null || !(detailInfo instanceof List)){
            return;
        }
        List<MonitorItemDto> itemDtos = JSONArray.parseArray(JSON.toJSONString(detailInfo), MonitorItemDto.class);
        if(CollectionUtils.isEmpty(itemDtos)){
            return;
        }
        //键值
        List<String> keys = itemDtos.stream().filter(item -> StringUtils.isNotEmpty(item.getKeyValue())).map(s -> s.getKeyValue()).collect(Collectors.toList());
        String assetsIp = param.getAssetsIp();//分发主机IP
        List<String> ip = new ArrayList<>();
        ip.add(assetsIp);
        //获取键值对应脚本
        for (String key:keys) {
            String configName = UUID.randomUUID()+".config";
            AutopsReferencingScript autopsReferencingScript = opsengineApi.SelectZabbixAutopsScript(key);
            if (autopsReferencingScript!=null){
                String name = opsengineApi.SelectZabbixAutopsScriptType(autopsReferencingScript.getAutopsScriptTypeId());
                FileInfo jsonObject = new FileInfo();
                try {
                    jsonObject = FilePost.uploadFile(autopsReferencingScript.getAutopsReferencingScriptContent()
                            ,name,url,menuId,accountId,userid,fileType);
                    JSONObject jsonObject1 = FilePost.sendFile(workflowId,sendUrl,accountId,userid,workOrderId,destinationPath,ip,List.of(jsonObject));
                    jsonObject = FilePost.uploadFile(FilePost.content(autopsReferencingScript.getAutopsReferencingScriptVariableList(),destinationPath)
                            ,configName,url,menuId,accountId,userid,fileType);
                    JSONObject jsonObject2 = FilePost.sendFile(workflowId,sendUrl,accountId,userid,workOrderId,destinationPath,ip,List.of(jsonObject));
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }


    }


    private String matchItemName(String itemName){
        // 正则表达式，用于匹配监控项名称
        String regex = "\\[(.*?)\\]";
        // 创建 Pattern 对象
        Pattern pattern = Pattern.compile(regex);
        // 创建 Matcher 对象
        Matcher matcher = pattern.matcher(itemName);
        while (matcher.find()){
            return matcher.group(1);
        }
        return null;
    }

    private String matchInterfaceName(String interfaceName){
        // 正则表达式，用于匹配接口名称
        String regex = "\\[(.*?)-?\\]";
        // 创建 Pattern 对象
        Pattern pattern = Pattern.compile(regex);
        // 创建 Matcher 对象
        Matcher matcher = pattern.matcher(interfaceName);
        while (matcher.find()){
            return matcher.group(1);
        }
        return null;
    }

    private void hanlderFilter(Map zabbixParam){
        if(zabbixParam.containsKey(FILTER)){
            DiscoveryRuleFilterParam filterParam = (DiscoveryRuleFilterParam) zabbixParam.get(FILTER);
            Map map = ListMapObjUtils.beanToMap(filterParam);
            List<DiscoveryRuleFilterParam.FilterCondition> conditions = filterParam.getConditions();
            List<Map> listMaps = new ArrayList<>();
            for (DiscoveryRuleFilterParam.FilterCondition condition : conditions) {
                Map beanToMap = ListMapObjUtils.beanToMap(condition);
                delMapNullValue(beanToMap);
                listMaps.add(beanToMap);
            }
            map.put(CONDITIONS,listMaps);
            delMapNullValue(map);
            zabbixParam.put(FILTER,map);
        }
    }

    public void delMapNullValue(Map zabbixParam){
        Iterator iterator = zabbixParam.entrySet().iterator();
        while (iterator.hasNext()){
            Map.Entry entry = (Map.Entry) iterator.next();
            if(entry.getValue() == null){
                iterator.remove();
            }else if(entry.getValue() instanceof List){
                List list = (List) entry.getValue();
                if(CollectionUtils.isEmpty(list)){
                    iterator.remove();
                }
            }
        }
    }
}
